﻿using System.Globalization;
using System.IO;
using Avalonia.Platform;
using KinonekoSoftware.CodariaDB.Core;
using KinonekoSoftware.Studio.Utils;


namespace KinonekoSoftware.Studio.Resources.Converters
{
    public abstract class ImageConverterBase<TEngine> : ImageConverterBase where TEngine : _File
    {
        public const string URI_IMAGE_AVATAR      = "avares://KinonekoSoftware.Studio.Views.Tablet/Assets/avatar.png";
        public const string URI_IMAGE_COVER       = "avares://KinonekoSoftware.Studio.Views.Tablet/Assets/Images/album.png";
        public const string URI_IMAGE_MASKED_ICON = "avares://KinonekoSoftware.Studio.Views.Tablet/Assets/Images/album.png";
        
        private       TEngine _engine;


        protected virtual Bitmap GetImage(Stream stream)
        {
            var ms = new MemoryStream((int)stream.Length);
            stream.CopyTo(ms);
            stream.Dispose();
            ms.Seek(0, SeekOrigin.Begin);
            return MediaFactory.ToBitmap(ms);
        }

        /// <summary>
        /// 根据指定的ID获取IO流
        /// </summary>
        /// <param name="id">图片的ID</param>
        /// <returns>返回指定ID的文件流，可能会返回null。</returns>
        protected virtual Stream GetStream(string id)
        {
            try
            {
                return Engine.Open(id);
            }
            catch
            {
                return null;
            }
        }
        
        /// <summary>
        /// 根据指定的ID获取图片。
        /// </summary>
        /// <param name="id">图片的ID</param>
        /// <returns>返回指定ID所对应的图片或者返回回滚图片。</returns>
        protected virtual Bitmap GetImage(string id)
        {
            if (string.IsNullOrEmpty(id))
            {
                return GetFallbackImage();
            }

            Bitmap bi;
            Stream      stream;
            
            if (!Platform.Cache.TryGetValue(id, out var wBI))
            {
                stream = GetStream(id);
                if (stream is null)
                {
                    return GetFallbackImage();
                }
                
                bi  = GetImage(stream);
                wBI = new WeakReference<object>(bi);
                Platform.Cache.TryAdd(id, wBI);
                return bi;
            }

            if (!wBI.TryGetTarget(out var v) || v is not Bitmap)
            {
                Xplat.Debug($"Bitmap is not active, reCreate :{id}");
                stream = GetStream(id);
                bi     = GetImage(stream);
                wBI.SetTarget(bi);
            }

            bi = (Bitmap)v;
            return bi;
        }
        
        /// <summary>
        /// 获取回滚图片。
        /// </summary>
        /// <returns>返回回滚图片。</returns>
        protected abstract Bitmap GetFallbackImage();
            
        public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is null)
            {
                return GetFallbackImage();
            }
            
            //
            // image uri
            var uri = value.ToString();
            
            //
            //
            try
            {
                return GetImage(uri);
            }
            catch
            {
                return GetFallbackImage();
            }
        }
        
        public TEngine Engine
        {
            get
            {
                _engine ??= Platform.GetEngine<TEngine>();
                return _engine;
            }
        }
    }
    
    
    public abstract class ImageConverterBase : ConverterBase
    {
        
        public static Bitmap Open(Uri uri)
        {
            return new Bitmap(AssetLoader.Open(uri));
        }
    }

}